
/****************************************************************************
**
** Copyright (C) 2004-2008 VATATA.com . All rights reserved.
**
** This file is the part of the Miniutil Poject of VATATA.com.
** Vatata's miniutil library is lightweight and portable (for linux
** and Windows). The C++ Class Library included Threadpool, Dll danymic loading, 
** General socket application model and tcp server, httpserver/servlet, etc. 
** It is a pratical utility disigned for who don't want learn the Big C++ 
** Developing Platform, such as  Boost or ACE.
**
** This file may be used under the terms of the GNU General Public
** License versions 2.0 or 3.0 as published by the Free Software
** Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file.  Alternatively you may (at
** your option) use any later version of the GNU General Public
** License if such license has been publicly approved by VATATA.com.
** (or its successors, if any) and the Miniutil Project Aministrators. 
**
** Please review the following information to ensure GNU General
** Public Licensing requirements will be met:
** http://www.gnu.org/licenses/lgpl.html. If you are unsure which 
** license is appropriate for your use, please review the following 
** information: http://code.google.com/p/miniutil/ or contact 
** http://www.vatata.com.
**
** In addition, as a special exception, VATATA.com, as the sole
** copyright holder for Miniutil Project, grants users of VATATA
** P2P Platform the right to release and package with the related 
** libraries without the source code.
**
** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE. vatata reserves all rights not expressly
** granted herein.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/



#ifndef __MINIUTIL__COUNTER__H___
#define __MINIUTIL__COUNTER__H___

#include <string>
#include <map>

#include "miniutil/datatype.h"
#include "miniutil/thread.h"

/*
    counter usage:

    in CPP file, using such MACRO:

    //---------------------------------------

    MINI_DEFI_STATIC_COUNTER_VALUE(socketacceptnum)

    MINI_BEGIN_STATIC_COUNTER_GROUP(socket)
    MINI_STATIC_COUNTER("sys.socket.acceptnum", socketacceptnum)
    MINI_END_STATIC_COUNTER_GROUP

    //---------------------------------------

    or you can define class counter value by 
    MINI_DECLARE_CLASS_COUNTER_VALUE
    MINI_DEFI_CLASS_COUNTER_VALUE

    then you can use variable socketacceptnum in that file.
    such as
    socketacceptnum ++;

    if you want to bind them to actual counter class and reference them.
    you can write such code in any place, suggest place is main function

    //---------------------------------------
        MINI_BIND_STATIC_COUNTER_GROUP(socket)
    //---------------------------------------
    that's all
    now you can reference the counter through

    *miniutil::sys::counter::stmap_smunit64[sys.socket.acceptnum];

    if you want to add counter dynamically during task running, you can do following:

    MINI_BIND_COUNTER("sys.socket.acceptnum", socketacceptnum);

*/

namespace miniutil
{
	namespace sys
	{
        class counter
        {
            public:
		        static std::map<std::string, miniutil::m_uint64_t *> stmap_smunit64;
                static ::miniutil::mutex couter_mtx;
            public:

		        static std::map<std::string, miniutil::m_uint64_t *> * get_counters_map();

		        static void bind_counter( const std::string & name, miniutil::m_uint64_t * p );
		        static void bind_counter_nolock( const std::string & name, miniutil::m_uint64_t * p );
        };

		template <class _Func>
		static inline void for_each_counter( _Func &func)
		{
            std::map<std::string, miniutil::m_uint64_t *> * p_counters = counter::get_counters_map();

			std::map<std::string, m_uint64_t *>::iterator i = p_counters->begin();
			while( i != p_counters->end() )
			{
				func( i->first, i->second );
				i++;
			}
		}

	}
}

#define MINI_DECLARE_CLASS_COUNTER_VALUE(valuenm) \
    static unsigned long long valuenm;

#define MINI_DEFI_CLASS_COUNTER_VALUE(classnm, valuenm) \
    unsigned long long classnm::valuenm = 0;

#define MINI_DEFI_STATIC_COUNTER_VALUE(valuenm) \
    static unsigned long long valuenm = 0;
    
#define MINI_BEGIN_STATIC_COUNTER_GROUP(countername) \
    void* countername[][2] = { 
    
#define MINI_STATIC_COUNTER(name, value) \
    {(void*)name, (void*)&value},

#define MINI_END_STATIC_COUNTER_GROUP \
    {(void*)0x00, (void*)0x00} \
    };

#define MINI_BIND_STATIC_COUNTER_GROUP(countername) \
    { \
        extern void* countername[][2]; \
        int i=0; \
        while(true) \
        { \
            if(countername[i][0] == (void*)0x00) \
                break; \
                miniutil::sys::counter::bind_counter_nolock((char*)countername[i][0], (unsigned long long*)countername[i][1]); \
            i ++; \
        } \
    }


#define MINI_BIND_COUNTER(name, value) \
    { \
        miniutil::sys::counter::bind_counter((const char*)name, (unsigned long long*)&value); \
    }

#define MINI_UNBIND_COUNTER(name) \
    { \
        miniutil::sys::counter::bind_counter((char*)name, (unsigned long long*)0x00); \
    }


#endif
